import {join} from 'path';
import {AutoBackupConfig, BackupMetadata, RecoveryPoint} from '../types';
import {FileUtil} from './fileUtil';

/**
 * 备份管理器
 */
export class BackupManager {
    /**
     * 备份目录路径
     */
    private backupDir: string;
    /**
     * 备份配置
     */
    private config: AutoBackupConfig;
    /**
     * 备份元数据文件路径
     */
    private metadataPath: string;
    /**
     * 恢复点文件路径
     */
    private recoveryPointsPath: string;
    /**
     * 自动备份计时器
     */
    private backupInterval?: NodeJS.Timeout;
    /**
     * 待备份文件变更记录
     */
    private pendingChanges: Map<string, {
        content: string;
        timestamp: number;
        backupScheduled: boolean;
    }>;

    /**
     * 构造函数
     * @param rootPath 根目录路径
     * @param config 备份配置
     */
    constructor(rootPath: string, config: AutoBackupConfig) {
        this.config = config;
        this.backupDir = join(rootPath, '.backup');
        this.metadataPath = join(this.backupDir, 'metadata.json');
        this.recoveryPointsPath = join(this.backupDir, 'recovery-points.json');
        this.pendingChanges = new Map();
    }

    /**
     * 初始化备份管理器
     */
    async initialize(): Promise<void> {
        await FileUtil.createDirectory(this.backupDir);

        // 确保元数据文件存在
        if (!await FileUtil.exists(this.metadataPath)) {
            await FileUtil.writeFile(this.metadataPath, JSON.stringify([]));
        }

        if (!await FileUtil.exists(this.recoveryPointsPath)) {
            await FileUtil.writeFile(this.recoveryPointsPath, JSON.stringify([]));
        }

        // 启动自动备份
        if (this.config.enabled) {
            this.startAutoBackup();
        }

        // 清理过期备份
        await this.cleanupExpiredBackups();
    }

    /**
     * 记录文件变更
     * @param fileId 文件ID
     * @param content 文件内容
     */
    async recordChange(fileId: string, content: string): Promise<void> {
        if (!this.config.enabled) {
            return;
        }

        this.pendingChanges.set(fileId, {
            content,
            timestamp: Date.now(),
            backupScheduled: false
        });

        // 安排备份
        await this.scheduleBackup(fileId);
    }

    /**
     * 安排备份
     * @param fileId 文件ID
     */
    private async scheduleBackup(fileId: string): Promise<void> {
        const change = this.pendingChanges.get(fileId);
        if (!change || change.backupScheduled) {
            return;
        }

        change.backupScheduled = true;

        // 延迟执行备份，以合并短时间内的多次修改
        setTimeout(async () => {
            await this.createBackup(fileId, change.content, 'auto');
            this.pendingChanges.delete(fileId);
        }, 1000);
    }

    /**
     * 创建备份
     * @param fileId 文件ID
     * @param content 文件内容
     * @param type 备份类型
     */
    private async createBackup(fileId: string, content: string, type: 'auto' | 'manual'): Promise<void> {
        const backupId = `${fileId}-${Date.now()}`;
        const backupPath = join(this.backupDir, backupId);

        try {
            // 检查备份大小
            if (content.length > this.config.maxBackupSize) {
                console.warn(`文件过大，跳过备份: ${fileId}`);
                return;
            }

            // 写入备份文件
            await FileUtil.writeFile(backupPath, content);

            // 更新元数据
            const metadata: BackupMetadata = {
                id: backupId,
                fileId,
                backupTime: Date.now(),
                type,
                size: content.length,
                fileState: {
                    relativePath: fileId,
                    lastModified: Date.now(),
                    size: content.length
                }
            };

            const metadataList = await this.getBackupMetadata();
            metadataList.push(metadata);

            // 限制备份数量
            while (metadataList.length > this.config.maxBackups) {
                const oldestBackup = metadataList.shift();
                if (oldestBackup) {
                    await this.deleteBackup(oldestBackup.id);
                }
            }

            await FileUtil.writeFile(this.metadataPath, JSON.stringify(metadataList));
        } catch (error) {
            console.error('创建备份失败:', error);
        }
    }

    /**
     * 删除备份
     * @param backupId 备份ID
     */
    private async deleteBackup(backupId: string): Promise<void> {
        const backupPath = join(this.backupDir, backupId);
        if (await FileUtil.exists(backupPath)) {
            await FileUtil.delete(backupPath);
        }
    }

    /**
     * 获取备份元数据列表
     */
    private async getBackupMetadata(): Promise<BackupMetadata[]> {
        const content = await FileUtil.readFile(this.metadataPath);
        return JSON.parse(content);
    }

    /**
     * 创建恢复点
     * @param description 恢复点描述
     */
    async createRecoveryPoint(description: string): Promise<RecoveryPoint> {
        const recoveryPoint: RecoveryPoint = {
            id: Date.now().toString(),
            createTime: Date.now(),
            description,
            files: await this.getBackupMetadata()
        };

        const points = await this.getRecoveryPoints();
        points.push(recoveryPoint);
        await FileUtil.writeFile(this.recoveryPointsPath, JSON.stringify(points));

        return recoveryPoint;
    }

    /**
     * 获取恢复点列表
     */
    async getRecoveryPoints(): Promise<RecoveryPoint[]> {
        const content = await FileUtil.readFile(this.recoveryPointsPath);
        return JSON.parse(content);
    }

    /**
     * 从恢复点恢复
     * @param recoveryPointId 恢复点ID
     */
    async restoreFromPoint(recoveryPointId: string): Promise<boolean> {
        const points = await this.getRecoveryPoints();
        const point = points.find(p => p.id === recoveryPointId);

        if (!point) {
            return false;
        }

        for (const file of point.files) {
            const backupPath = join(this.backupDir, file.id);
            if (await FileUtil.exists(backupPath)) {
                const content = await FileUtil.readFile(backupPath);
                // 这里需要调用文件空间的恢复方法
                // 实际恢复逻辑需要在FileSpace类中实现
                await this.onRestore?.(file.fileId, content);
            }
        }

        return true;
    }

    /**
     * 清理过期备份
     */
    private async cleanupExpiredBackups(): Promise<void> {
        const metadata = await this.getBackupMetadata();
        const now = Date.now();

        const validBackups = metadata.filter(backup => {
            const age = now - backup.backupTime;
            return age <= this.config.retentionTime;
        });

        for (const backup of metadata) {
            if (!validBackups.includes(backup)) {
                await this.deleteBackup(backup.id);
            }
        }

        await FileUtil.writeFile(this.metadataPath, JSON.stringify(validBackups));
    }

    /**
     * 启动自动备份
     */
    private startAutoBackup(): void {
        if (this.backupInterval) {
            clearInterval(this.backupInterval);
        }

        this.backupInterval = setInterval(async () => {
            for (const [fileId, change] of this.pendingChanges) {
                if (!change.backupScheduled) {
                    await this.scheduleBackup(fileId);
                }
            }
        }, this.config.interval);
    }

    /**
     * 停止自动备份
     */
    stopAutoBackup(): void {
        if (this.backupInterval) {
            clearInterval(this.backupInterval);
            this.backupInterval = undefined;
        }
    }

    /**
     * 恢复回调函数
     */
    public onRestore?: (fileId: string, content: string) => Promise<void>;
}
